import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { SecurityEventEmitter } from '../events/security-event.emitter';

@Injectable()
export class SecurityLogInterceptor implements NestInterceptor {
  private readonly logger = new Logger(SecurityLogInterceptor.name);

  constructor(private readonly securityEventEmitter: SecurityEventEmitter) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const response = context.switchToHttp().getResponse();
    const startTime = Date.now();

    // 提取请求信息
    const requestInfo = this.extractRequestInfo(request);

    return next.handle().pipe(
      tap((data) => {
        // 记录成功的请求（可选，主要用于审计）
        this.logSuccessfulRequest(requestInfo, data, Date.now() - startTime);
      }),
      catchError((error) => {
        // 记录异常信息
        this.logError(requestInfo, error, Date.now() - startTime);
        return throwError(() => error);
      }),
    );
  }

  /**
   * 提取请求信息
   */
  private extractRequestInfo(request: any) {
    return {
      url: request.url,
      method: request.method,
      headers: request.headers,
      body: request.body,
      params: request.params,
      query: request.query,
      user: request.user,
      ip: this.getClientIp(request),
      userAgent: request.headers['user-agent'],
      referer: request.headers.referer,
    };
  }

  /**
   * 获取客户端IP地址
   */
  private getClientIp(request: any): string {
    return (
      request.headers['x-forwarded-for'] ||
      request.headers['x-real-ip'] ||
      request.connection?.remoteAddress ||
      request.socket?.remoteAddress ||
      request.ip ||
      'unknown'
    );
  }

  /**
   * 记录成功的请求
   */
  private async logSuccessfulRequest(requestInfo: any, responseData: any, executionTime: number) {
    try {
      // 只记录需要审计的请求
      if (this.shouldAuditRequest(requestInfo)) {
        this.securityEventEmitter.emitAuthSuccess({
          eventTitle: '请求成功',
          eventDescription: `用户 ${requestInfo.user?.username || 'anonymous'} 成功访问 ${requestInfo.url}`,
          userId: requestInfo.user?.id,
          username: requestInfo.user?.username,
          ipAddress: requestInfo.ip,
          userAgent: requestInfo.userAgent,
          requestUrl: requestInfo.url,
          requestMethod: requestInfo.method,
          additionalInfo: {
            executionTime,
            referer: requestInfo.referer,
            responseData: this.sanitizeResponse(responseData),
          },
        });
      }
    } catch (error) {
      this.logger.error('记录成功请求失败', error.stack);
    }
  }

  /**
   * 记录错误信息
   */
  private async logError(requestInfo: any, error: any, executionTime: number) {
    try {
      const { eventType, securityLevel, eventTitle, eventDescription } = this.analyzeError(error);
      
      // 根据错误类型发射相应的事件
      switch (eventType) {
        case 'UNAUTHORIZED_ACCESS':
          this.securityEventEmitter.emitUnauthorizedAccess({
            eventTitle,
            eventDescription,
            userId: requestInfo.user?.id,
            username: requestInfo.user?.username,
            ipAddress: requestInfo.ip,
            userAgent: requestInfo.userAgent,
            requestUrl: requestInfo.url,
            requestMethod: requestInfo.method,
            additionalInfo: {
              executionTime,
              referer: requestInfo.referer,
              errorCode: this.getErrorCode(error),
              httpStatusCode: this.getHttpStatusCode(error),
            },
          });
          break;
        case 'PERMISSION_DENIED':
          this.securityEventEmitter.emitPermissionDenied({
            eventTitle,
            eventDescription,
            userId: requestInfo.user?.id,
            username: requestInfo.user?.username,
            ipAddress: requestInfo.ip,
            userAgent: requestInfo.userAgent,
            requestUrl: requestInfo.url,
            requestMethod: requestInfo.method,
            additionalInfo: {
              executionTime,
              referer: requestInfo.referer,
              errorCode: this.getErrorCode(error),
              httpStatusCode: this.getHttpStatusCode(error),
            },
          });
          break;
        case 'VALIDATION_ERROR':
          this.securityEventEmitter.emitValidationError({
            eventTitle,
            eventDescription,
            userId: requestInfo.user?.id,
            username: requestInfo.user?.username,
            ipAddress: requestInfo.ip,
            userAgent: requestInfo.userAgent,
            requestUrl: requestInfo.url,
            requestMethod: requestInfo.method,
            errorMessage: error.message || '未知错误',
            additionalInfo: {
              executionTime,
              referer: requestInfo.referer,
              errorCode: this.getErrorCode(error),
              httpStatusCode: this.getHttpStatusCode(error),
            },
          });
          break;
        case 'RATE_LIMIT_EXCEEDED':
          this.securityEventEmitter.emitRateLimitExceeded({
            eventTitle,
            eventDescription,
            userId: requestInfo.user?.id,
            username: requestInfo.user?.username,
            ipAddress: requestInfo.ip,
            userAgent: requestInfo.userAgent,
            requestUrl: requestInfo.url,
            requestMethod: requestInfo.method,
            additionalInfo: {
              executionTime,
              referer: requestInfo.referer,
              errorCode: this.getErrorCode(error),
              httpStatusCode: this.getHttpStatusCode(error),
            },
          });
          break;
        default:
          // 系统错误或其他错误
          this.securityEventEmitter.emitSystemError({
            eventTitle,
            eventDescription,
            userId: requestInfo.user?.id,
            username: requestInfo.user?.username,
            ipAddress: requestInfo.ip,
            userAgent: requestInfo.userAgent,
            requestUrl: requestInfo.url,
            requestMethod: requestInfo.method,
            errorMessage: error.message || '未知错误',
            stackTrace: error.stack,
            additionalInfo: {
              executionTime,
              referer: requestInfo.referer,
              errorCode: this.getErrorCode(error),
              httpStatusCode: this.getHttpStatusCode(error),
            },
          });
      }
    } catch (logError) {
      this.logger.error('记录错误信息失败', logError.stack);
    }
  }

  /**
   * 分析错误类型
   */
  private analyzeError(error: any) {
    let eventType = 'SYSTEM_ERROR';
    let securityLevel = 'MEDIUM';
    let eventTitle = '系统错误';
    let eventDescription = '系统发生未知错误';

    if (error instanceof HttpException) {
      const status = error.getStatus();
      
      switch (status) {
        case HttpStatus.UNAUTHORIZED:
          eventType = 'UNAUTHORIZED_ACCESS';
          securityLevel = 'HIGH';
          eventTitle = '未授权访问';
          eventDescription = '用户尝试访问未授权的资源';
          break;
        case HttpStatus.FORBIDDEN:
          eventType = 'PERMISSION_DENIED';
          securityLevel = 'HIGH';
          eventTitle = '权限拒绝';
          eventDescription = '用户权限不足，访问被拒绝';
          break;
        case HttpStatus.BAD_REQUEST:
          eventType = 'VALIDATION_ERROR';
          securityLevel = 'MEDIUM';
          eventTitle = '请求参数错误';
          eventDescription = '请求参数验证失败';
          break;
        case HttpStatus.NOT_FOUND:
          eventType = 'OTHER';
          securityLevel = 'LOW';
          eventTitle = '资源未找到';
          eventDescription = '请求的资源不存在';
          break;
        case HttpStatus.TOO_MANY_REQUESTS:
          eventType = 'RATE_LIMIT_EXCEEDED';
          securityLevel = 'HIGH';
          eventTitle = '请求频率超限';
          eventDescription = '用户请求频率超过限制';
          break;
        default:
          if (status >= 500) {
            eventType = 'SYSTEM_ERROR';
            securityLevel = 'HIGH';
            eventTitle = '服务器内部错误';
            eventDescription = '服务器发生内部错误';
          }
      }
    } else if (error.name === 'ValidationError') {
      eventType = 'VALIDATION_ERROR';
      securityLevel = 'MEDIUM';
      eventTitle = '数据验证错误';
      eventDescription = '数据验证失败';
    } else if (error.name === 'TypeError') {
      eventType = 'SYSTEM_ERROR';
      securityLevel = 'HIGH';
      eventTitle = '类型错误';
      eventDescription = '系统发生类型错误';
    }

    return { eventType, securityLevel, eventTitle, eventDescription };
  }

  /**
   * 获取错误代码
   */
  private getErrorCode(error: any): string {
    if (error instanceof HttpException) {
      return `HTTP_${error.getStatus()}`;
    }
    return error.name || 'UNKNOWN_ERROR';
  }

  /**
   * 获取HTTP状态码
   */
  private getHttpStatusCode(error: any): number {
    if (error instanceof HttpException) {
      return error.getStatus();
    }
    return 500;
  }

  /**
   * 判断是否需要审计请求
   */
  private shouldAuditRequest(requestInfo: any): boolean {
    // 只审计敏感操作，如POST、PUT、DELETE等
    const sensitiveMethods = ['POST', 'PUT', 'DELETE', 'PATCH'];
    return sensitiveMethods.includes(requestInfo.method);
  }

  /**
   * 清理响应数据
   */
  private sanitizeResponse(responseData: any): any {
    if (!responseData) return null;
    
    // 移除敏感信息
    const sanitized = { ...responseData };
    delete sanitized.password;
    delete sanitized.token;
    delete sanitized.secret;
    
    return sanitized;
  }
}
